package com.yisin.pbox.frame.base;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.dom4j.Attribute;
import org.dom4j.Element;

import com.yisin.pbox.frame.log.ILogger;
import com.yisin.pbox.frame.log.LogFactory;
import com.yisin.pbox.frame.util.StringUtil;
import com.yisin.pbox.frame.util.XmlParser;

public class ServletFilter implements Filter {
	private static final long serialVersionUID = 1L;
	ILogger logger = LogFactory.getDefaultLogger(ServletFilter.class);
	static String[] defauntFilter = { "jpg", "gif", "png", "bmp", "css", "js", "html", "htm", "jsp" };
	static String[] filter = null;

	public ServletFilter() {
		super();
	}

	public void init(FilterConfig arg0) throws ServletException {
		String root = arg0.getServletContext().getContextPath();
		ServerGlobals.ROOT_NAME = root;

		String path = arg0.getServletContext().getRealPath("/");

		try {
			String config = arg0.getInitParameter("config");
			if(StringUtil.isEmpty(config)){
				config = "/WEB-INF/config/action.xml";
			}
			File configFile = new File(path + config);
			if(!configFile.exists()){
				throw new FileNotFoundException("not found for action.xml.");
			}
			
			String filters = arg0.getInitParameter("filter");
			if(!StringUtil.isEmpty(filters)){
				filter = filters.split(",");
			}
			
			ServerGlobals.ACTION_XML = config;
			parseActionXml(path);
		} catch (Exception e) {
			e.printStackTrace();
		}
		logger.debug("root name is " + root);
	}

	public void destroy() {

	}

	/**
	 * @see HttpServlet#service(HttpServletRequest request, HttpServletResponse
	 *      response)
	 */
	protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

	}

	private boolean isExist(String uri) {
		String zui = uri.substring(uri.lastIndexOf(".") + 1);
		for (int i = 0, k = defauntFilter.length; i < k; i++) {
			if (defauntFilter[i].equals(zui)) {
				return true;
			}
		}
		if(filter != null){
			for (int i = 0, k = filter.length; i < k; i++) {
				if (filter[i].equals(zui)) {
					return true;
				}
			}
		}
		return false;
	}

	public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2) throws IOException, ServletException {
		HttpServletRequest request = (HttpServletRequest) arg0;
		HttpServletResponse response = (HttpServletResponse) arg1;
		System.out.println(request.getRequestURL());
		String uri = request.getRequestURI();
		uri = uri.substring((ServerGlobals.ROOT_NAME).length());
		if (!isExist(uri)) {
			ActionBean ab = ActionHelper.excute(uri, request.getQueryString(), request, response);
			if (null != ab) {
				String url = ab.getResult().get(ab.getResultName());
				if(StringUtil.isEmpty(url) && !StringUtil.isEmpty(ab.getResultName())){
					url = ab.getResultName();
				}
				if (!StringUtil.isEmpty(url)) {
					if (ab.isRedirect()) {
						if (null != ab.getXss()) {
							response.setHeader("X-XSS-Protection", ab.getXss());
						}
						response.sendRedirect(ServerGlobals.ROOT_NAME + url);
					} else {
						request.getRequestDispatcher(url).forward(request, response);
					}
				}
			}
		} else {
			arg2.doFilter(request, response);
		}
	}
	
	
	public void parseActionXml(String path) throws Exception {

		Element root = XmlParser.getRootNode(path + ServerGlobals.ACTION_XML);

		List<Element> packages = XmlParser.getChildList(root);

		Attribute packnameAttr = null, spaceAttr = null, 
				nameAttr = null, classAttr = null, methodAttr = null, xssAttr = null, 
				paramAttr = null, derrAttr = null;
		String packname = "", namespace = "", 
		name = "", className = "", xss = "", method = "", derr = "";
		List<Element> resultChild = null;

		List<Element> actions = null;
		
		for (Element pack : packages) {
			
			packnameAttr = XmlParser.getAttribute(pack, "name");
			spaceAttr = XmlParser.getAttribute(pack, "namespace");
			if (null != packnameAttr) {
				packname = packnameAttr.getValue();
			}
			if (null != spaceAttr) {
				namespace = spaceAttr.getValue();
			}
			
			// 判断命名空间是否为空，是否重复
			if(StringUtil.isEmpty(namespace)){
				throw new Exception("package namespace is empty.");
			}
			if(ActionHelper.actionMap.containsKey(namespace)){
				throw new Exception("package namespace is repeat.");
			}
			
			// 获取到pack下的所有action
			actions = XmlParser.getChildList(pack);
			if(null != actions && actions.size() > 0){
				
				for (Element action : actions) {
					
					nameAttr = XmlParser.getAttribute(action, "name");
					classAttr = XmlParser.getAttribute(action, "class");
					methodAttr = XmlParser.getAttribute(action, "method");
					derrAttr = XmlParser.getAttribute(action, "redirect");
					xssAttr = XmlParser.getAttribute(action, "xss");
					
					if (null != nameAttr) {
						name = nameAttr.getValue();
					}
					if (null != classAttr) {
						className = classAttr.getValue();
					}
					if (null != methodAttr) {
						method = methodAttr.getValue();
					}
					if (null != xssAttr) {
						xss = xssAttr.getValue();
					}
					if (null != derrAttr) {
						derr = derrAttr.getValue();
					}
					
					resultChild = XmlParser.getChildList(action);
					
					Map<String, String> result = new HashMap<String, String>();
					
					if (resultChild.size() > 0) {
						for (Element child : resultChild) {
							paramAttr = XmlParser.getAttribute(child, "name");
							result.put(paramAttr.getValue(), child.getText());
						}
					}
					
					ActionHelper.add(name, className, method, namespace, derr, xss, result);
				}
			}

		}
	}
	
	
}
